package org.dromara.ai.security;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * AI内容过滤服务
 * 提供敏感内容检测、过滤和安全控制功能
 *
 * @author ruoyi
 * @date 2024-01-01
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class AiContentFilterService {

    /**
     * 内容过滤结果
     */
    public static class FilterResult {
        private boolean passed;
        private String filteredContent;
        private List<String> violations;
        private double riskScore;
        private String riskLevel;
        private Map<String, Object> details;

        public FilterResult(boolean passed, String filteredContent) {
            this.passed = passed;
            this.filteredContent = filteredContent;
            this.violations = new ArrayList<>();
            this.riskScore = 0.0;
            this.riskLevel = "LOW";
            this.details = new HashMap<>();
        }

        // Getters and Setters
        public boolean isPassed() { return passed; }
        public void setPassed(boolean passed) { this.passed = passed; }
        public String getFilteredContent() { return filteredContent; }
        public void setFilteredContent(String filteredContent) { this.filteredContent = filteredContent; }
        public List<String> getViolations() { return violations; }
        public void setViolations(List<String> violations) { this.violations = violations; }
        public double getRiskScore() { return riskScore; }
        public void setRiskScore(double riskScore) { this.riskScore = riskScore; }
        public String getRiskLevel() { return riskLevel; }
        public void setRiskLevel(String riskLevel) { this.riskLevel = riskLevel; }
        public Map<String, Object> getDetails() { return details; }
        public void setDetails(Map<String, Object> details) { this.details = details; }
    }

    /**
     * 过滤策略枚举
     */
    public enum FilterStrategy {
        STRICT,     // 严格模式
        MODERATE,   // 中等模式
        LENIENT     // 宽松模式
    }

    /**
     * 违规类型枚举
     */
    public enum ViolationType {
        PROFANITY,          // 脏话
        HATE_SPEECH,        // 仇恨言论
        VIOLENCE,           // 暴力内容
        SEXUAL_CONTENT,     // 性内容
        ILLEGAL_ACTIVITY,   // 非法活动
        PERSONAL_INFO,      // 个人信息
        SPAM,               // 垃圾信息
        MALICIOUS_CODE,     // 恶意代码
        POLITICAL_SENSITIVE, // 政治敏感
        COMMERCIAL_AD       // 商业广告
    }

    // 敏感词库
    private static final Set<String> PROFANITY_WORDS = Set.of(
        "fuck", "shit", "damn", "bitch", "asshole", "bastard"
        // 这里应该包含更完整的敏感词库
    );

    private static final Set<String> HATE_SPEECH_WORDS = Set.of(
        "nazi", "terrorist", "kill", "murder", "genocide"
        // 仇恨言论关键词
    );

    private static final Set<String> VIOLENCE_WORDS = Set.of(
        "bomb", "weapon", "gun", "knife", "attack", "violence"
        // 暴力相关关键词
    );

    private static final Set<String> SEXUAL_WORDS = Set.of(
        "porn", "sex", "nude", "naked", "adult"
        // 性内容关键词
    );

    // 正则表达式模式
    private static final Pattern EMAIL_PATTERN = Pattern.compile(
        "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}"
    );
    
    private static final Pattern PHONE_PATTERN = Pattern.compile(
        "\\b\\d{3}-\\d{3}-\\d{4}\\b|\\b\\d{10}\\b|\\(\\d{3}\\)\\s*\\d{3}-\\d{4}"
    );
    
    private static final Pattern ID_CARD_PATTERN = Pattern.compile(
        "\\b\\d{15}|\\d{18}\\b"
    );

    private static final Pattern MALICIOUS_CODE_PATTERN = Pattern.compile(
        "<script[^>]*>.*?</script>|javascript:|eval\\(|exec\\(|system\\(",
        Pattern.CASE_INSENSITIVE | Pattern.DOTALL
    );

    /**
     * 过滤输入内容
     *
     * @param content 待过滤内容
     * @param strategy 过滤策略
     * @return 过滤结果
     */
    public FilterResult filterInput(String content, FilterStrategy strategy) {
        if (content == null || content.trim().isEmpty()) {
            return new FilterResult(true, content);
        }

        FilterResult result = new FilterResult(true, content);
        String filteredContent = content;
        List<String> violations = new ArrayList<>();
        double riskScore = 0.0;

        // 1. 检测脏话
        FilterResult profanityResult = checkProfanity(filteredContent, strategy);
        if (!profanityResult.isPassed()) {
            violations.addAll(profanityResult.getViolations());
            filteredContent = profanityResult.getFilteredContent();
            riskScore += 10;
        }

        // 2. 检测仇恨言论
        FilterResult hateSpeechResult = checkHateSpeech(filteredContent, strategy);
        if (!hateSpeechResult.isPassed()) {
            violations.addAll(hateSpeechResult.getViolations());
            riskScore += 30;
        }

        // 3. 检测暴力内容
        FilterResult violenceResult = checkViolence(filteredContent, strategy);
        if (!violenceResult.isPassed()) {
            violations.addAll(violenceResult.getViolations());
            riskScore += 25;
        }

        // 4. 检测性内容
        FilterResult sexualResult = checkSexualContent(filteredContent, strategy);
        if (!sexualResult.isPassed()) {
            violations.addAll(sexualResult.getViolations());
            riskScore += 20;
        }

        // 5. 检测个人信息
        FilterResult personalInfoResult = checkPersonalInfo(filteredContent, strategy);
        if (!personalInfoResult.isPassed()) {
            violations.addAll(personalInfoResult.getViolations());
            filteredContent = personalInfoResult.getFilteredContent();
            riskScore += 15;
        }

        // 6. 检测恶意代码
        FilterResult maliciousCodeResult = checkMaliciousCode(filteredContent, strategy);
        if (!maliciousCodeResult.isPassed()) {
            violations.addAll(maliciousCodeResult.getViolations());
            riskScore += 40;
        }

        // 7. 检测垃圾信息
        FilterResult spamResult = checkSpam(filteredContent, strategy);
        if (!spamResult.isPassed()) {
            violations.addAll(spamResult.getViolations());
            riskScore += 5;
        }

        // 设置结果
        result.setFilteredContent(filteredContent);
        result.setViolations(violations);
        result.setRiskScore(riskScore);
        result.setRiskLevel(calculateRiskLevel(riskScore));
        result.setPassed(violations.isEmpty() || isAcceptableRisk(riskScore, strategy));

        // 记录详细信息
        Map<String, Object> details = new HashMap<>();
        details.put("originalLength", content.length());
        details.put("filteredLength", filteredContent.length());
        details.put("strategy", strategy.name());
        details.put("violationCount", violations.size());
        result.setDetails(details);

        log.info("Content filter result: passed={}, riskScore={}, violations={}", 
                result.isPassed(), riskScore, violations.size());

        return result;
    }

    /**
     * 过滤输出内容
     *
     * @param content 待过滤内容
     * @param strategy 过滤策略
     * @return 过滤结果
     */
    public FilterResult filterOutput(String content, FilterStrategy strategy) {
        // 输出过滤通常比输入过滤更严格
        FilterResult result = filterInput(content, strategy);
        
        // 额外的输出特定检查
        if (result.isPassed()) {
            // 检查是否包含可能的提示注入攻击
            if (containsPromptInjection(content)) {
                result.setPassed(false);
                result.getViolations().add("PROMPT_INJECTION");
                result.setRiskScore(result.getRiskScore() + 50);
                result.setRiskLevel("HIGH");
            }
        }

        return result;
    }

    /**
     * 检测脏话
     */
    private FilterResult checkProfanity(String content, FilterStrategy strategy) {
        FilterResult result = new FilterResult(true, content);
        String lowerContent = content.toLowerCase();
        String filteredContent = content;
        
        for (String word : PROFANITY_WORDS) {
            if (lowerContent.contains(word)) {
                result.setPassed(false);
                result.getViolations().add(ViolationType.PROFANITY.name() + ": " + word);
                
                // 根据策略决定是否替换
                if (strategy == FilterStrategy.STRICT || strategy == FilterStrategy.MODERATE) {
                    filteredContent = filteredContent.replaceAll(
                        "(?i)" + Pattern.quote(word), "*".repeat(word.length())
                    );
                }
            }
        }
        
        result.setFilteredContent(filteredContent);
        return result;
    }

    /**
     * 检测仇恨言论
     */
    private FilterResult checkHateSpeech(String content, FilterStrategy strategy) {
        FilterResult result = new FilterResult(true, content);
        String lowerContent = content.toLowerCase();
        
        for (String word : HATE_SPEECH_WORDS) {
            if (lowerContent.contains(word)) {
                result.setPassed(false);
                result.getViolations().add(ViolationType.HATE_SPEECH.name() + ": " + word);
            }
        }
        
        return result;
    }

    /**
     * 检测暴力内容
     */
    private FilterResult checkViolence(String content, FilterStrategy strategy) {
        FilterResult result = new FilterResult(true, content);
        String lowerContent = content.toLowerCase();
        
        for (String word : VIOLENCE_WORDS) {
            if (lowerContent.contains(word)) {
                result.setPassed(false);
                result.getViolations().add(ViolationType.VIOLENCE.name() + ": " + word);
            }
        }
        
        return result;
    }

    /**
     * 检测性内容
     */
    private FilterResult checkSexualContent(String content, FilterStrategy strategy) {
        FilterResult result = new FilterResult(true, content);
        String lowerContent = content.toLowerCase();
        
        for (String word : SEXUAL_WORDS) {
            if (lowerContent.contains(word)) {
                result.setPassed(false);
                result.getViolations().add(ViolationType.SEXUAL_CONTENT.name() + ": " + word);
            }
        }
        
        return result;
    }

    /**
     * 检测个人信息
     */
    private FilterResult checkPersonalInfo(String content, FilterStrategy strategy) {
        FilterResult result = new FilterResult(true, content);
        String filteredContent = content;
        
        // 检测邮箱
        if (EMAIL_PATTERN.matcher(content).find()) {
            result.setPassed(false);
            result.getViolations().add(ViolationType.PERSONAL_INFO.name() + ": EMAIL");
            if (strategy != FilterStrategy.LENIENT) {
                filteredContent = EMAIL_PATTERN.matcher(filteredContent)
                    .replaceAll("[EMAIL_REDACTED]");
            }
        }
        
        // 检测电话号码
        if (PHONE_PATTERN.matcher(content).find()) {
            result.setPassed(false);
            result.getViolations().add(ViolationType.PERSONAL_INFO.name() + ": PHONE");
            if (strategy != FilterStrategy.LENIENT) {
                filteredContent = PHONE_PATTERN.matcher(filteredContent)
                    .replaceAll("[PHONE_REDACTED]");
            }
        }
        
        // 检测身份证号
        if (ID_CARD_PATTERN.matcher(content).find()) {
            result.setPassed(false);
            result.getViolations().add(ViolationType.PERSONAL_INFO.name() + ": ID_CARD");
            if (strategy != FilterStrategy.LENIENT) {
                filteredContent = ID_CARD_PATTERN.matcher(filteredContent)
                    .replaceAll("[ID_REDACTED]");
            }
        }
        
        result.setFilteredContent(filteredContent);
        return result;
    }

    /**
     * 检测恶意代码
     */
    private FilterResult checkMaliciousCode(String content, FilterStrategy strategy) {
        FilterResult result = new FilterResult(true, content);
        
        if (MALICIOUS_CODE_PATTERN.matcher(content).find()) {
            result.setPassed(false);
            result.getViolations().add(ViolationType.MALICIOUS_CODE.name());
        }
        
        return result;
    }

    /**
     * 检测垃圾信息
     */
    private FilterResult checkSpam(String content, FilterStrategy strategy) {
        FilterResult result = new FilterResult(true, content);
        
        // 简单的垃圾信息检测逻辑
        String lowerContent = content.toLowerCase();
        
        // 检测重复字符
        if (hasExcessiveRepetition(content)) {
            result.setPassed(false);
            result.getViolations().add(ViolationType.SPAM.name() + ": REPETITION");
        }
        
        // 检测常见垃圾词汇
        String[] spamWords = {"free", "win", "prize", "click here", "buy now"};
        for (String word : spamWords) {
            if (lowerContent.contains(word)) {
                result.setPassed(false);
                result.getViolations().add(ViolationType.SPAM.name() + ": " + word);
                break;
            }
        }
        
        return result;
    }

    /**
     * 检测提示注入攻击
     */
    private boolean containsPromptInjection(String content) {
        String lowerContent = content.toLowerCase();
        String[] injectionPatterns = {
            "ignore previous instructions",
            "forget everything above",
            "new instructions:",
            "system prompt:",
            "act as",
            "pretend to be",
            "roleplay as"
        };
        
        for (String pattern : injectionPatterns) {
            if (lowerContent.contains(pattern)) {
                return true;
            }
        }
        
        return false;
    }

    /**
     * 检测过度重复
     */
    private boolean hasExcessiveRepetition(String content) {
        if (content.length() < 10) {
            return false;
        }
        
        // 检测连续重复字符
        int maxRepeat = 0;
        int currentRepeat = 1;
        char lastChar = content.charAt(0);
        
        for (int i = 1; i < content.length(); i++) {
            if (content.charAt(i) == lastChar) {
                currentRepeat++;
            } else {
                maxRepeat = Math.max(maxRepeat, currentRepeat);
                currentRepeat = 1;
                lastChar = content.charAt(i);
            }
        }
        
        return maxRepeat > 5; // 超过5个连续相同字符认为是垃圾信息
    }

    /**
     * 计算风险等级
     */
    private String calculateRiskLevel(double riskScore) {
        if (riskScore >= 50) {
            return "HIGH";
        } else if (riskScore >= 20) {
            return "MEDIUM";
        } else if (riskScore > 0) {
            return "LOW";
        } else {
            return "NONE";
        }
    }

    /**
     * 判断风险是否可接受
     */
    private boolean isAcceptableRisk(double riskScore, FilterStrategy strategy) {
        switch (strategy) {
            case STRICT:
                return riskScore < 10;
            case MODERATE:
                return riskScore < 30;
            case LENIENT:
                return riskScore < 50;
            default:
                return false;
        }
    }

    /**
     * 获取过滤统计信息
     */
    public Map<String, Object> getFilterStats() {
        Map<String, Object> stats = new HashMap<>();
        stats.put("profanityWordsCount", PROFANITY_WORDS.size());
        stats.put("hateSpeechWordsCount", HATE_SPEECH_WORDS.size());
        stats.put("violenceWordsCount", VIOLENCE_WORDS.size());
        stats.put("sexualWordsCount", SEXUAL_WORDS.size());
        stats.put("supportedViolationTypes", ViolationType.values().length);
        stats.put("availableStrategies", FilterStrategy.values());
        return stats;
    }
}